import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;
import java.util.*;
import java.lang.*;
/**
 * PicGen -  a random picture generator
 *
 * @author Quinn Damerell
 */
public class MainWindow extends JFrame implements ComponentListener, Runnable, ActionListener, ChangeListener {
	int windowX,windowY,picX,picY,random,shades,changeCur,shadeInc,pixCount;
	int fixX; // the correction for the X
    int fixY; // the correction for the Y
    int[] grid; //holds all the pixles
	int[] change; //holds all the pixles
	int delay;
	boolean run;
	JSlider rate;
    Thread process;
	GraphicsPanel main;

    public MainWindow(int winX,int winY, int piX, int piY, int rand, int sha) {
		windowX = winX;
		windowY = winY;
		picX = piX;
		picY = piY;
		random = rand;
		shades = sha-1;		
		main = new GraphicsPanel();
		main.addComponentListener(this);
		main.setPreferredSize(new Dimension(windowX,windowY));	
		getContentPane().add(main);		
		JFrame control = new JFrame("Controls");
		JPanel holder = new JPanel();
		JPanel buttons = new JPanel();
		JButton pause = new JButton("Pause");
		JButton resume = new JButton("Resume");
		pause.addActionListener(this);
		resume.addActionListener(this);
		rate = new JSlider(JSlider.HORIZONTAL,0,30,0);
		rate.addChangeListener(this);
		rate.setMajorTickSpacing(10);
		rate.setMinorTickSpacing(1);
		rate.setPaintTicks(true);
		rate.setPaintLabels(true);
		buttons.add(pause);
		buttons.add(resume);
		buttons.add(rate);
		holder.setLayout(new BorderLayout());
		holder.add(buttons,BorderLayout.CENTER);
		JLabel info = new JLabel("Created by: Quinn Damerell                                Delay");
		holder.add(info,BorderLayout.SOUTH);
		control.getContentPane().add(holder);
		control.pack();
		control.setVisible(true);	
		control.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);		
		control.setLocation(0,windowY+40);
		pack();		
			
		//Initalize
		grid = new int[picX*picY];
		change = new int[picX*picY];
		changeCur = 0;
		pixCount = 0;
		delay = 0;
		process = new Thread(this);
	}
	
	public void runLoop(){
        Random rand = new Random(); //create a random object
        fixX = windowX/picX; //is the percent that the X must be modified to fit the window
        fixY = windowY/picY; //is the percent that the Y must be modified to fit the window
        shadeInc = (int)Math.ceil(256/shades);//Set the correct quality out of 255 insted of the shade number
		run = true;
        for (int x = 0; x < picX*picY; x++) grid[x] = 0; //sets all the elements to the grid to 0
        if (random == 0){
            for (int x = 0; x < picX*picY; x++){
                grid[x] = rand.nextInt(256);
				//change[changeCur] = x;
				//changeCur++;
            }
        }
		process.start();
	}

    public void run() {
		int tempCount;
		int done = 0;
		while(true){
			if(run){		
				if (grid[pixCount] > 254){
					tempCount = 0;
					while (grid[tempCount] >= 255) tempCount++;
					//once found add the new value in
					grid[tempCount] = grid[tempCount] + shadeInc;
					done++;
					if (grid[tempCount] > 255) grid[tempCount] = 255; //IDK what this does

					//Next we need to go backward and set all to 0 and redraw
					tempCount--;
					while (tempCount >= 0)
					{
						grid[tempCount] = 0;
						tempCount--;
					}
					pixCount=0;
				}
				else{
					grid[pixCount] = grid[pixCount] + shadeInc;
					done++;
					if(grid[pixCount] > 255){
						grid[pixCount] = 255;
					}
				}
				main.repaint();
				main.validate();
				try {
					Thread.sleep(delay);
				} 
				catch (InterruptedException e) {
					break;
				}	
			}							
		}
    }

	public void componentResized(ComponentEvent e) {
		Dimension d = e.getComponent().size();
		windowX = (int)d.getWidth();
		windowY = (int)d.getHeight();
		fixX = windowX/picX;
        fixY = windowY/picY;
		setPreferredSize(new Dimension(windowX,windowY));
		repaint();		
    }
	public void componentHidden(ComponentEvent evt) {
	}

	public void componentMoved(ComponentEvent evt) {

	}

	public void componentShown(ComponentEvent evt) {
	}
	public void actionPerformed(ActionEvent e) {
        if (e.getActionCommand().equals("Pause")) {
			run = false;
			delay = 100;
        }
		else if (e.getActionCommand().equals("Resume")) {
			run = true;
			delay = (int)rate.getValue();
        }
    }
	
	public void stateChanged(ChangeEvent e) {
		if (!rate.getValueIsAdjusting()) {
			delay = (int)rate.getValue();			
		}
	}
    public void stop() {
		process = null;
    }
	public class GraphicsPanel extends JPanel{
		public void paint(Graphics g) {
			for (int x = 0; x < picX*picY; x++){
				if(grid[x] > 255){g.setColor(new Color(255,255,255));grid[x] = 255;}
				else {
					g.setColor(new Color(grid[x],grid[x],grid[x]));
				}
				g.fillRect(fixX*(x%picX), fixY*(x/picX), fixX, fixY);
			}
		}
	}
}



/*
    private boolean Running = true; //if the program is running
    static int fixX; // the correction for the X
    static int fixY; // the correction for the Y
    static int[] grid; //holds all the pixles
	static int[] change; //holds all the pixles
	static int changeCur, horz, vert;
	MainGraphics main;

	
	// Construct and set it running.
	 
	public MainWindow() {		
		main = new MainGraphics();
		main.setPreferredSize(new Dimension(800,600));
		getContentPane().add(main);
		pack();	
	}

    /*The main methoid that runs the program
     *
     *  arguments horz - the horzontal pixels
     *  arguments vert - the vertical pixels
     *  arguments quality - the number of steps in the shades
     *  arguments random - start with random pixles 0 or 1
     
	public void mainLoop(int horzA, int vertA, int quality, int random) {
		horz = horzA;
		vert = vertA;		
        Random rand = new Random(); //create a random object
        long secCounter = System.currentTimeMillis(); //keeps track of the cycle time
        int numPerSec = 0; //the number of cycles per sec
        int tempNumPerSec = 0; //the add up to the number of cycles per sec
        double possible = Math.pow(quality,horz*vert); //lists the number of possible options
        boolean inf = false; //sees if possible is infiant
        double done = 0; //keeps track of the number of completed cycles
        double percent = 0; //percent done
        int currentCount = 0; //the current grid number that the program is on
        int tempCount = 0; //a temp count of which grid place the program is on

        //Intalize varables
        grid = new int[horz*vert]; //an array that keeps all the elements of the grid and the current shade
        change = new int[horz*vert];
		changeCur = 0;
		fixX = 800/horz; //is the percent that the X must be modified to fit the window
        fixY = 600/vert; //is the percent that the Y must be modified to fit the window
        quality = (int)Math.ceil(257/(quality-1));//Set the correct quality out of 255 insted of the shade number
        for (int x = 0; x < horz*vert; x++) grid[x] = 0; //sets all the elements to the grid to 0
        if (Double.isInfinite(possible)) inf = true; //checks to see if possible is infinite

        //Setup
        if (random == 0){
            for (int x = 0; x < horz*vert; x++){
                grid[x] = rand.nextInt(256);
				change[changeCur] = x;
				changeCur++;
            }
        }
		main.paint();
        done++;

        //THE MAIN PROGRAM LOOP
        while (Running) {
            //rolls over the secCounter when it his a sec and records the cycles
            if (System.currentTimeMillis() - secCounter >= 1000){
                secCounter = System.currentTimeMillis();
                numPerSec = tempNumPerSec;
                tempNumPerSec = 0;
            }
            else {
                tempNumPerSec++;
            }System.out.println(changeCur);
			main.repaint();
/*			
            //Draws the bottom menu bar
            g.setColor(Color.blue);
            g.fillRect(0, 600, 800, 20);
            g.setColor(Color.white);
            //find the percent
            if(done%400 == 0){
                percent = done/possible*100;
            }
            //check to see which String to draw
            if (inf){
                 g.drawString("Cycles/Second: "+numPerSec+"   Possible Combinations: >1.7E+308   Done: "+done+"   Percent Done: "+percent,0,615);
            }
            else{
                g.drawString("Cycles/Second: "+numPerSec+"   Possible Combinations: "+possible+"   Done: "+done+"   Percent Done: "+percent,0,615);
            }

            //Start the real Pixel switch
            //first we find if we need to roll the pixel values
            if (grid[currentCount] > 255){
                tempCount = 0;
                //Find the next pixel that can be filled
                while (grid[tempCount] > 255) tempCount++;
                //once found add the new value in
                grid[tempCount] = grid[tempCount] + quality;

                if (grid[tempCount] > 255) grid[tempCount] = 255; //IDK what this does

                //draw in the pixel with the size offset
				change[changeCur] = tempCount;
				changeCur++;
				
                done++;

                if (grid[tempCount] == 255) grid[tempCount] = 256; //IDK what this does

                //Next we need to go backward and set all to 0 and redraw
                tempCount--;
                while (tempCount >= 0)
                {
                    grid[tempCount] = 0;
                    change[changeCur] = tempCount;
					changeCur++;
                    tempCount--;
                }

            }
            else{//Lastly if not just update the grid like normal
                grid[currentCount] = grid[currentCount] + quality;
                if (grid[currentCount] > 255) grid[currentCount] = 255;
                change[changeCur] = currentCount;
				changeCur++;
                done++;
                if (grid[currentCount] == 255) grid[currentCount] = 256;
            }//reset else
        }
	}	

	public static class MainGraphics extends JPanel {
        public MainGraphics() {
		
		}  
		
        public void paint(Graphics g) {
			System.out.println("bob");
			super.paintComponent(g); 
			Graphics2D g2d =(Graphics2D)g;
			for (int x = 0; x < changeCur; x++){
                g.setColor(new Color(grid[change[x]],grid[change[x]],grid[change[x]]));
                g.fillRect(fixX*(change[x]%horz), fixY*(change[x]/horz), fixX, fixY);
            }
			changeCur = 0;
        }
	}	
} */